#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "json_cfg.h"
#include "cJSON.h"
#include "log.h"

static int read_json_config_file(char* path, char* data)
{
	FILE *fp;
	int len;
	fp = fopen(path,"r");
	if(!fp){
		DBG(DBG_ERR,"can not open file\n");
		return -ENODEV;
	}
	fseek(fp,0,SEEK_END);
	len = ftell(fp);
	fseek(fp,0,SEEK_SET);
	fread(data,1,len,fp);
	fclose(fp);
	return 0;
}

static int json_read_int_value(cJSON* sjson, const char* type, int default_value)
{
	if(!sjson){
		return default_value;
	}
	cJSON* djson = cJSON_GetObjectItem(sjson, type);
    if (djson) {
        return djson->valueint;
    }else{
		return default_value;
	}
}

static const char* json_read_string_value(cJSON* sjson, const char* type, const char* default_value)
{
	if(!sjson){
		return default_value;
	}
	cJSON* djson = cJSON_GetObjectItem(sjson, type);
    if (djson) {
        return djson->valuestring;
    }else{
		return default_value;
	}
}

int read_json_config(char* path, struct config_param* params)
{
	int32_t ret;
	cJSON* json;
	char data[2048] = {0};
	int fps = 29;

	if (!params) {
		return -EINVAL;
	}
	if (!path) {
		ret = read_json_config_file((char*)__CONFIG_FILE_PATH__, data);
	}
	else {
		if(strlen(path) > 4){
			ret = read_json_config_file(path, data);
		}else{
			ret = read_json_config_file((char*)__CONFIG_FILE_PATH__, data);
		}
	}
	if (ret < 0) {
		DBG(DBG_ERR, "can not open json file\n");
	}
	json = cJSON_Parse(data);

	params->vi_width = json_read_int_value(json, "vi_width", 1920);
	params->vi_height = json_read_int_value(json, "vi_height", 1080);
	strncpy(params->vi_pix_fmt, json_read_string_value(json, "vi_pix_fmt", "yuv420"), 16);
	params->vi_fps = json_read_int_value(json, "vi_fps", fps);
	DBG(DBG_INFO, "vi fps = %d\n", params->vi_fps);
	params->vi_crop_x = json_read_int_value(json, "vi_crop_x", 0);
	params->vi_crop_y = json_read_int_value(json, "vi_crop_y", 0);
	params->vi_crop_width = json_read_int_value(json, "vi_crop_width", 1920);
	params->vi_crop_height = json_read_int_value(json, "vi_crop_height", 1080);

	params->encoder_width = json_read_int_value(json, "encoder_width", 1920);
	params->encoder_height = json_read_int_value(json, "encoder_height", 1080);
	strncpy(params->encoder_type, json_read_string_value(json, "encoder_type", "h264"), 16);
	params->encoder_gop = json_read_int_value(json, "encoder_gop", fps);
	params->encoder_fps = json_read_int_value(json, "encoder_fps", fps);
	params->encoder_bps = json_read_int_value(json, "encoder_bps", 6000);

	params->vo_width = json_read_int_value(json, "vo_width", 1920);
	params->vo_height = json_read_int_value(json, "vo_height", 1080);
	params->vo_fps = json_read_int_value(json, "vo_fps", fps);
	strncpy(params->vo_pix_fmt, json_read_string_value(json, "vo_pix_fmt", "yuv420"), 16);
	
	params->rtsp_port = json_read_int_value(json, "rtsp_port", 554);
	strncpy(params->ip, json_read_string_value(json, "ip", "192.168.20.123"), 16);

	if(json){
		cJSON_Delete(json);
	}
	return 0;
}

int write_json_config(char* path, struct config_param* params)
{
	char buffer[10240];

	sprintf(buffer, "\
			{\n\
			\"vi_width\":%d,\n\
			\"vi_height\":%d,\n\
			\"vi_pix_fmt\":\"%s\",\n\
			\"vi_fps\":%d,\n\
			\"vi_crop_x\":%d,\n\
			\"vi_crop_y\":%d,\n\
			\"vi_crop_width\":%d,\n\
			\"vi_crop_height\":%d,\n\
			\"encoder_width\":%d,\n\
			\"encoder_height\":%d,\n\
			\"encoder_type\":\"%s\",\n\
			\"encoder_gop\":%d,\n\
			\"encoder_fps\":%d,\n\
			\"encoder_bps\":%d,\n\
			\"vo_width\":%d,\n\
			\"vo_height\":%d,\n\
			\"vo_fps\":%d,\n\
			\"vo_pix_fmt\":\"%s\",\n\
			\"rtsp_port\":%d,\n\
			\"ip\":\"%s\"\n\
			}",
		params->vi_width, params->vi_height,
		params->vi_pix_fmt, params->vi_fps,
		params->vi_crop_x, params->vi_crop_y,
		params->vi_crop_width, params->vi_crop_height,
		params->encoder_width, params->encoder_height,
		params->encoder_type, params->encoder_gop,
		params->encoder_fps, params->encoder_bps,
		params->vo_width, params->vo_height,
		params->vo_fps, params->vo_pix_fmt,
		params->rtsp_port,
		params->ip);

	FILE *fp;
	if(!path){
		fp = fopen(__CONFIG_FILE_PATH__, "w");
	}else{
		if(strlen(path) > 4){
			fp = fopen(path, "w");
		}else{
			fp = fopen(__CONFIG_FILE_PATH__, "w");
		}
	}
	if(!fp){
		DBG(DBG_ERR,"can not open file\n");
		return -ENODEV;
	}
	fwrite(buffer, strlen(buffer), 1,fp);
	fclose(fp);
	return 0;
}

#define UCONTROL_PARAM_PATH "/root/ucontrol_param"
void read_ucontrol_param(struct ucontrol_param* param)
{
	FILE* fp;
	fp = fopen(UCONTROL_PARAM_PATH, "rb");
	if(!fp){
		param->defog_flag = 0;
		param->defog_value = 128;
		param->contrast_value = 50;
		param->brightness_value = 80;
		param->zoom_value = 1;
		param->enhance_flag = param->defog_flag;
		param->enhance_value = param->defog_value;
		param->gain_flag = 0;
		param->gain_value = 0;

		param->osd_flag = 0;
		param->crossline_flag = 0;
		param->crossline_x = 1920 / 2;
		param->crossline_y = 1080 / 2;
	}else{
		fread(param, sizeof(struct ucontrol_param), 1, fp);
		fclose(fp);

		if(param->defog_value < 0){
			param->defog_value = 0;
		}
		if(param->defog_value > 255){
			param->defog_value = 255;
		}
		if(param->contrast_value < 0){
			param->contrast_value = 0;
		}
		if(param->contrast_value > 100){
			param->contrast_value = 100;
		}
		if(param->brightness_value < 0){
			param->brightness_value = 0;
		}
		if(param->brightness_value > 255){
			param->brightness_value = 80;
		}
		if(param->zoom_value != 1 && param->zoom_value != 2 && param->zoom_value != 4){
			param->zoom_value = 1;
		}
		if(param->enhance_value < 0){
			param->enhance_value = 0;
		}
		if(param->enhance_value > 255){
			param->enhance_value = 255;
		}
		if(param->gain_value < 0){
			param->gain_value = 0;
		}
		if(param->crossline_x < 100){
			param->crossline_x = 100;
		}
		if(param->crossline_x > 1920 - 100){
			param->crossline_x = 1920 - 100;
		}
		param->crossline_x = IMAGE_ALIGN(param->crossline_x, 2);
		if(param->crossline_y < 100){
			param->crossline_y = 100;
		}
		if(param->crossline_y > 1080 - 100){
			param->crossline_y = 1080 - 100;
		}
		param->crossline_y = IMAGE_ALIGN(param->crossline_y, 2);
	}
}

void write_ucontrol_param(struct ucontrol_param* param)
{
	FILE* fp;
	if(param->defog_value < 0){
		param->defog_value = 0;
	}
	if(param->defog_value > 255){
		param->defog_value = 255;
	}
	if(param->contrast_value < 0){
		param->contrast_value = 0;
	}
	if(param->contrast_value > 100){
		param->contrast_value = 100;
	}
	if(param->brightness_value < 0){
		param->brightness_value = 0;
	}
	if(param->brightness_value > 255){
		param->brightness_value = 80;
	}
	if(param->zoom_value != 1 && param->zoom_value != 2 && param->zoom_value != 4){
		param->zoom_value = 1;
	}
	if(param->enhance_value < 0){
		param->enhance_value = 0;
	}
	if(param->enhance_value > 255){
		param->enhance_value = 255;
	}
	if(param->gain_value < 0){
		param->gain_value = 0;
	}
	if(param->crossline_x < 100){
		param->crossline_x = 100;
	}
	if(param->crossline_x > 1920 - 100){
		param->crossline_x = 1920 - 100;
	}
	param->crossline_x = IMAGE_ALIGN(param->crossline_x, 2);
	if(param->crossline_y < 100){
		param->crossline_y = 100;
	}
	if(param->crossline_y > 1080 - 100){
		param->crossline_y = 1080 - 100;
	}
	param->crossline_y = IMAGE_ALIGN(param->crossline_y, 2);
	fp = fopen(UCONTROL_PARAM_PATH, "wb");
	if(fp){
		fwrite(param, sizeof(struct ucontrol_param), 1, fp);
		fclose(fp);
	}
	sync();
}

void clear_ucontrol_param()
{
	remove(UCONTROL_PARAM_PATH);
}

